package ctu.kfad.run;

import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class ClassFileRepository {

    private File base;
    private Map<String, JavaClass> loadedClasses = new HashMap<>();

    public ClassFileRepository(File base) {
        this.base = base;
    }


    public JavaClass loadClass(String className) {
        if (className == null || className.equals("")) {
            throw new IllegalArgumentException("Invalid class name " + className);
        }
        JavaClass javaClass = loadedClasses.get(className);
        if (javaClass != null) {
            return javaClass;
        }
        try {
            return loadClassFromBase(className);
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException("Exception while looking for class " + className + ": " + e, e);
        }
    }

    private JavaClass loadClassFromBase(String className) throws ClassNotFoundException, FileNotFoundException {
        String fileName = className.replace(".", "/") + ".class";
        FileInputStream fileInputStream = new FileInputStream(new File(base, fileName));
        try (InputStream is = fileInputStream) {
            if (is != null) {
                ClassParser parser = new ClassParser(is, className);
                JavaClass clazz = parser.parse();
                loadedClasses.put(className, clazz);
                return clazz;
            }
        } catch (IOException e) {
            throw new ClassNotFoundException("Exception while looking for class " + className + ": " + e, e);
        }
        throw new ClassNotFoundException(getClass().getSimpleName() + " could not load " + className);
    }

}
